package com.appspot.bibtable.view.html;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Field;
import java.util.logging.Logger;

import com.appspot.bibtable.model.Reference;
import com.appspot.bibtable.model.ReferenceEntity;
import com.appspot.bibtable.model.annotation.Input;
import com.appspot.bibtable.util.ReflectionUtility;
import com.appspot.bibtable.view.TableCellType;

public abstract class ReferenceTable extends HtmlTable
{
	private static final Logger logger = Logger.getLogger(ReferenceTable.class.getName());

	private boolean documentRequired;

	public boolean isDocumentRequired()
	{
		return documentRequired;
	}

	public void setDocumentRequired(boolean documentRequired)
	{
		this.documentRequired = documentRequired;
	}

	@Override
	public void addReference(ReferenceEntity entity, Writer writer) throws IOException
	{
		Reference reference = entity.getReference();

		Class<?> c = reference.getClass();
		for (Field field : ReflectionUtility.getAllFields(c, true))
		{
			Input input = field.getAnnotation(Input.class);
			if (input == null)
			{
				continue;
			}

			String value = getValue(reference, field, input);
			String display = input.name().display();
			String document = input.document();

			addRow(writer, value, display, document);
		}

		try
		{
			Field tagField = ReferenceEntity.class.getDeclaredField("tag");
			Input input = tagField.getAnnotation(Input.class);

			String value = getValue(entity, tagField, input);
			String display = input.name().display();
			String document = input.document();

			addRow(writer, value, display, document);
		}
		catch (NoSuchFieldException ex)
		{
			logger.severe(ex.getClass().getName());
		}
	}
	
	private void addRow(Writer writer, String value, String display, String document) throws IOException
	{
		startRow(writer);

		startCell(writer, TableCellType.HEADING);
		writer.write(display);
		endCell(writer, TableCellType.HEADING);
		startCell(writer, TableCellType.NORMAL);
		if (value != null)
		{
			writer.write(value);
		}
		endCell(writer, TableCellType.NORMAL);
		if (isDocumentRequired())
		{
			startCell(writer, TableCellType.NORMAL);
			writer.write(document);
			endCell(writer, TableCellType.NORMAL);
		}
		endRow(writer);
	}

	protected abstract String getValue(Reference reference, Field field, Input input);
}
